//
// Created by Administrator on 25-8-13.
//

#include "ntpclient.h"


#include "lwip/sockets.h"
#include "lwip/netdb.h"
#include "FreeRTOS.h"
#include "task.h"
#include "printf_rtos.h"
#include "semphr.h"
#include "system_api.h"
#include "event_groups.h"
#include "freertos_demo.h"
extern EventGroupHandle_t g_init_eventgroup;
extern SemaphoreHandle_t g_dns_mutex;
// NTP 客户端任务函数
void ntp_client_task(void* pvParams)
{
    // 1. 等待网络和DNS服务就绪
    xEventGroupWaitBits(g_init_eventgroup, BIT_DNS_READY, pdFALSE, pdTRUE, portMAX_DELAY);
    printf_rtos("NTP Client Task started.\n");

    bool is_first_sync_done = false;

    // --- 2. 主循环：定期同步时间 ---
    for (;;)
    {
        struct addrinfo hints;
        struct addrinfo *result = NULL;
        int client_socket = -1;
        int ret;

        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;

        // --- 2a. DNS查询 (在循环内，保证健壮性) ---
        xSemaphoreTake(g_dns_mutex, portMAX_DELAY);
        ret = getaddrinfo(NTP_SERVER_NAME, NTP_SERVER_PORT_STR, &hints, &result);
        xSemaphoreGive(g_dns_mutex);

        if (ret != 0) {
            printf_rtos("NTP DNS lookup failed, retrying in 1 min...\n");
            vTaskDelay(pdMS_TO_TICKS(60000));
            continue; // DNS失败，直接开始下一次大循环
        }
        printf_rtos("DNS for %s resolved successfully.\n", NTP_SERVER_NAME);

        // --- 2b. 创建Socket并发送NTP请求 ---
        client_socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
        if (client_socket < 0) {
            printf_rtos("NTP: Failed to create socket, errno:%d\n", errno);
            goto cleanup_and_delay; // 使用goto统一清理
        }

        ntp_packet packet = {0};
        packet.li_vn_mode = NTP_LI_VN_MODE;

        if (sendto(client_socket, &packet, sizeof(packet), 0, result->ai_addr, result->ai_addrlen) < 0) {
            printf_rtos("NTP: sendto failed, errno:%d\n", errno);
            goto cleanup_and_delay;
        }

        // --- 2c. 接收NTP响应 ---
        // 设置接收超时
        struct timeval receiving_timeout;
        receiving_timeout.tv_sec = 5; // 5秒超时
        receiving_timeout.tv_usec = 0;
        setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &receiving_timeout, sizeof(receiving_timeout));

        if (recvfrom(client_socket, &packet, sizeof(packet), 0, NULL, NULL) < sizeof(packet)) {
            printf_rtos("NTP: recvfrom failed or timeout, errno:%d\n", errno);
            goto cleanup_and_delay;
        }

        printf_rtos("NTP response received.\n");

        // --- 2d. 解析时间并更新系统 ---
        uint32_t ntp_timestamp = ntohl(packet.tx_ts_secs);
        time_t unix_timestamp = ntp_timestamp - NTP_TIMESTAMP_DELTA;
        time_t beijing_time = unix_timestamp + BEIJING_TIMEZONE_OFFSET;

        struct tm time_info;
        gmtime_r(&beijing_time, &time_info);
        sys_set_time(&time_info);
        sys_set_ntp_status(true);

        printf_rtos("----------------------------------------\n");
        printf_rtos("Current Time (UTC+8): %04d-%02d-%02d %02d:%02d:%02d\n",
                   time_info.tm_year + 1900, time_info.tm_mon + 1, time_info.tm_mday,
                   time_info.tm_hour, time_info.tm_min, time_info.tm_sec);
        printf_rtos("----------------------------------------\n");

        // --- 2e. 首次成功后，设置事件标志 ---
        if (!is_first_sync_done) {
            printf_rtos("First NTP sync successful. Setting event bit.\n");
            xEventGroupSetBits(g_init_eventgroup, BIT_NTP_READY);
            is_first_sync_done = true;
        }

    cleanup_and_delay:
        // --- 2f. 统一的清理步骤 ---
        if (client_socket >= 0) {
            closesocket(client_socket);
        }
        if (result != NULL) {
            freeaddrinfo(result); // *** 修复内存泄漏的关键 ***
        }

        // --- 2g. 延时，准备下一次同步 ---
        printf_rtos("NTP task will re-sync in 1 hour.\n");
        vTaskDelay(pdMS_TO_TICKS(3600 * 1000));
    }
}